

namespace Orz.LogManager
{
	//========================================================================
	// 	Imported Namespaces
	//========================================================================
	using System;
	using System.IO;
	using System.Windows.Forms;
	using System.Collections;
	using System.Xml;
	using Orz.Xml;
	using Orz.Parallel;
	using Orz.LogManager;
	using Orz.LogManager.Config;
	using Orz.Gui.Menus;
	using ICSharpCode.SharpZipLib.Zip;
	using Routrek.SSHC;
	
	
	///
	/// <summary>
	/// Represents the main GUI window of the application.
	/// </summary>
	/// <remarks>
	/// This class contains the functionality for the main window components
	/// such as the main menu.  It will work as an MDI parent, containing
	/// a number of <code>LoggingBaseForm</code> child windows.
	/// </remarks>
	///
	public class MainForm : System.Windows.Forms.Form
	{
		private System.Windows.Forms.MenuItem miMRU;
		private System.Windows.Forms.MenuItem mFile;
		private System.Windows.Forms.MenuItem menuItem14;
		private System.Windows.Forms.MenuItem miArrangeIcons;
		private System.Windows.Forms.MenuItem miOpenNewConfigurationFile;
		private System.Windows.Forms.MenuItem miExit;
		private System.Windows.Forms.MenuItem menuItem12;
		private System.Windows.Forms.MenuItem menuItem13;
		private System.Windows.Forms.MenuItem menuItem10;
		private System.Windows.Forms.MenuItem menuItem11;
		private System.Windows.Forms.MenuItem miOpen;
		private System.Windows.Forms.MenuItem menuItem17;
		private System.Windows.Forms.MenuItem miCascade;
		private System.Windows.Forms.MenuItem miReloadConfigurationFile;
		private System.Windows.Forms.MenuItem menuItem7;
		private System.Windows.Forms.MenuItem miUnpauseAll;
		private System.Windows.Forms.MenuItem menuItem18;
		private System.Windows.Forms.MenuItem menuItem19;
		private System.Windows.Forms.MenuItem menuItem20;
		private System.Windows.Forms.MenuItem menuItem23;
		private System.Windows.Forms.MenuItem mWindow;
		private System.Windows.Forms.MenuItem miFindNext;
		private System.Windows.Forms.MenuItem miSep99;
		private System.Windows.Forms.MenuItem miTileHorizonally;
		private System.Windows.Forms.MainMenu mainMenu;
		private System.Windows.Forms.MenuItem miFind;
		private System.Windows.Forms.MenuItem miClose;
		private System.Windows.Forms.MenuItem miClearAll;
		private System.Windows.Forms.MenuItem miTipOfTheDay;
		private System.Windows.Forms.MenuItem mView;
		private System.Windows.Forms.MenuItem miCopy;
		private System.Windows.Forms.MenuItem mEdit;
		private System.Windows.Forms.MenuItem miTileVertically;
		private System.Windows.Forms.MenuItem miAbout;
		private System.Windows.Forms.MenuItem miFindPrevious;
		private System.Windows.Forms.MenuItem miPrettyPrintXML;
		private System.Windows.Forms.MenuItem miSaveAll;
		private System.Windows.Forms.MenuItem xxx;
		private System.Windows.Forms.MenuItem miUnescapeQueryString;
		private System.Windows.Forms.MenuItem miEditConfigurationFile;
		private System.Windows.Forms.MenuItem miSave;
		private System.Windows.Forms.MenuItem miReloadAll;
		private System.Windows.Forms.MenuItem miCopyAll;
		private System.Windows.Forms.MenuItem menuItem16;
		private System.Windows.Forms.MenuItem miFilter;
		private System.Windows.Forms.MenuItem menuItem3;
		private System.Windows.Forms.MenuItem menuItem2;
		private System.Windows.Forms.MenuItem menuItem1;
		private System.Windows.Forms.MenuItem menuItem6;
		private System.Windows.Forms.MenuItem menuItem5;
		private System.Windows.Forms.MenuItem menuItem4;
		private System.Windows.Forms.MenuItem menuItem;
		private System.Windows.Forms.MenuItem menuItem9;
		private System.Windows.Forms.MenuItem menuItem8;
		private System.Windows.Forms.MenuItem miPauseAll;
		private System.Windows.Forms.MenuItem miPause;
		private System.Windows.Forms.MenuItem miReload;
		private System.Windows.Forms.MenuItem miPrettyPrintJSON;
		private System.Windows.Forms.MenuItem miClear;		
		//================================================================
		//
		//   PRIVATE DATA MEMBERS
//	 Most of these have been auto-generated for the GUI
		//
		//================================================================
		
		
		/// <summary>The path of the current config file</summary>
		private string sConfigFileName_i;
		
		/// <summary>The current search criteria for finding text</summary>
		private Finder finder_i = new Finder();
				
		/// <summary>The amount of zip compression to use (0=none, 9=best)</summary>
		private const int DEFAULT_ZIP_LEVEL = 5;
		
		private MRUList mruList_i;
		
		
		
		
		
		
		//================================================================
		//
		//   MAIN ENTRY POINT
		//
		//================================================================
		
		///
		/// <summary>
		/// The main entry point to the system.
		/// </summary>
		/// <remarks>
		/// This static method is called when the program is first started.
		/// It checks the command-line parameters for a configuration file name
		/// and creates the one and only instance of the MainForm class.
		/// 
		/// The only valid command-line syntax at present is:
		/// <bullet>LogManager [-configfile]</bullet>
		/// </remarks>
		///
		[STAThread]
		public static void Main(string[] args)
		{
			try
			{
				// set up the debug log
				SetupDebugLog();
				
				string sConfigFileName;
				
				if (0==args.Length)
				{
					LogsetManagerForm manager = new LogsetManagerForm();
					manager.ShowDialog();
					
					if (null == manager.SelectedLogset) return;
					
					sConfigFileName = manager.SelectedLogset.FileName;
					
				}
				else
				{
					if (2==args.Length  &&  (0==String.Compare(args[0], "-configfile", true)))
					{
						sConfigFileName = args[1];
					}
					else
					{
						LogError ("Main", "Syntax: Log Manager.exe [-configfile <file>]");
						return;
					}
				}
				
				if (! Path.IsPathRooted (sConfigFileName))
				{
					sConfigFileName = Application.StartupPath + "\\" + sConfigFileName;
				}
				
				
				Log.Debug("Starting with logfile <" + sConfigFileName +">");
				
				MainForm o = new MainForm(sConfigFileName);
				o.ShowDialog();
			}
			catch (Exception ex)
			{
				MessageBox.Show("Oh no!  An error!  What'll we do with it?  Can we keep it, huh?  Huh?\n" +
				                ex.Message + "\n" +
				                ex.StackTrace);
			}
		}
		
		
		
		
		//================================================================
		//
		//   CONSTRUCTORS
		//
		//================================================================
		
		
		///
		/// <summary>
		/// Stores the config filename and creates the child components.
		/// </summary>
		/// <remarks>
		/// This constructor will create and initialise all the form's
		/// child controls.  The rest of the startup functionality will
		/// take place when the form signals that it has loaded properly.
		/// </remarks>
		/// <seealso cref="CreatedFormLoad">See-also description</seealso>
		///
		public MainForm(string sConfigFileName_p)
		{
			sConfigFileName_i = sConfigFileName_p;
			InitializeComponent();
			
			mruList_i = new MRUList("Orz", "Log Manager", miMRU);
			mruList_i.MRUClick += new MRUList.MRUEventHandler(this.MRUClick);
		}
		
		
		
		
		
		
		//========================================================================
		//
		// 	 FORM EVENT HANDLERS
		//
		//========================================================================
		
		
		///
		/// <summary>
		/// FormLoad event handler.  Parses the config file and creates the individual logging windows.
		/// </summary>
		/// <remarks>
		/// Now that the parent form has been initialised properly, we can start
		/// adding in child forms - one for each log file to be tailed.
		/// </remarks>
		///
		void CreatedFormLoad(object sender, System.EventArgs e)
		{
			InitLogs(sConfigFileName_i);
			
			if (RegistrySettings.Get("Show tip on startup", "True") == "True")
			{
				try
				{
					TipOfTheDayForm f = new TipOfTheDayForm();
					f.ShowDialog();
				}
				catch (Exception ex)
				{
					// Don't care
				}
			}
		}
		
		
		
		///
		/// <summary>
		/// FormClosed event handler.
		/// </summary>
		/// <remarks>
		/// This event is not used at present
		/// </remarks>
		///
		void CreatedFormClosed(object sender, System.EventArgs e)
		{
		}
		
		
		
		///
		/// <summary>
		/// FormClosing event handler.
		/// </summary>
		/// <remarks>
		/// This event is fired when the form thinks it might be about to close.
		/// It calls the <code>Deinitialise</code> method on each of the active child forms.
		/// </remarks>
		///
		void CreatedFormClosing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			foreach (Form oForm in this.MdiChildren)
			{
				((LoggingBaseForm)oForm).Deinitialise();
			}
		}
		
		
		
		///
		/// <summary>
		/// Called when a child form is made active.
		/// </summary>
		///
		void CreatedFormMdiChildActivate(object sender, System.EventArgs e)
		{
			DoMdiChildActivate();
		}
		
		
		
		///
		/// <summary>
		/// Handles UI feedback for drag'n'drop - only "accepts" drop subjects that
		/// are files.
		/// </summary>
		///
		void MainFormDragEnter(object sender, System.Windows.Forms.DragEventArgs e)
		{
			if (e.Data.GetDataPresent(DataFormats.FileDrop))
			{
				e.Effect = DragDropEffects.Copy;
			}
			else
			{
				e.Effect = DragDropEffects.None;
			}
		}
		
		
		
		///
		/// <summary>
		/// Fired when a file is dropped on the main window - opens it just like
		/// the user had chosen it from an open file dialog.
		/// </summary>
		/// 
		void MainFormDragDrop(object sender, System.Windows.Forms.DragEventArgs e)
		{
			if (e.Data.GetDataPresent(DataFormats.FileDrop))
			{
				string[] vFileNames = (string[]) e.Data.GetData(DataFormats.FileDrop);
				
				DoOpen(vFileNames);
			}
		}
		
		
		
		
		
		
		
		
		
		//========================================================================
		//
		// 	 MENU EVENT HANDLERS
		//
		//========================================================================
		
		
		///
		/// <summary>
		/// This event handler is no longer used - it is still here because of a bug in the IDE.
		/// </summary>
		///
		void MUNUSEDClick(object sender, System.EventArgs e)
		{
			// Do nothing
		}
		
		
		
		///
		/// <summary>
		/// Exit menu event handler.  Attempts to close the main form.
		/// </summary>
		///
		void MiExitClick(object sender, System.EventArgs e)
		{
			this.Close();
		}
		
		///
		/// <summary>
		/// Tile Vertically menu event handler.  Changes the layout of the parent form.
		/// </summary>
		///
		void MiTileVerticallyClick(object sender, System.EventArgs e)
		{
			this.LayoutMdi (MdiLayout.TileVertical);
		}
		
		///
		/// <summary>
		/// Cascade menu event handler.  Changes the layout of the parent form.
		/// </summary>
		///
		void MiCascadeClick(object sender, System.EventArgs e)
		{
			this.LayoutMdi (MdiLayout.Cascade);
		}
		
		///
		/// <summary>
		/// Arrange Icons menu event handler.  Changes the layout of the parent form.
		/// </summary>
		///
		void MiArrangeIconsClick(object sender, System.EventArgs e)
		{
			this.LayoutMdi (MdiLayout.ArrangeIcons);
		}
		
		///
		/// <summary>
		/// Tile Horizontally menu event handler.  Changes the layout of the parent form.
		/// </summary>
		///
		void MiTileHorizonallyClick(object sender, System.EventArgs e)
		{
			this.LayoutMdi (MdiLayout.TileHorizontal);
		}
		
		///
		/// <summary>
		/// Copy menu event handler.
		/// </summary>
		/// <remarks>
		/// Just calls the <code>DoCopy</code> method to copy only the current selection.
		/// </remarks>
		///
		void MiCopyClick(object sender, System.EventArgs e)
		{
			DoCopy (true);
		}
		
		///
		/// <summary>
		/// Copy All menu event handler.
		/// </summary>
		/// <remarks>
		/// Just calls the <code>DoCopy</code> method to copy the entire window.
		/// </remarks>
		///
		void MiCopyAllClick(object sender, System.EventArgs e)
		{
			DoCopy (false);
		}
		
		///
		/// <summary>
		/// Open menu event handler
		/// </summary>
		///
		void MiOpenClick(object sender, System.EventArgs e)
		{
			DoOpen();
		}
		
		///
		/// <summary>
		/// Close menu event handler
		/// </summary>
		///
		void MiCloseClick(object sender, System.EventArgs e)
		{
			DoClose();
		}
		
		///
		/// <summary>
		/// Save menu event handler
		/// </summary>
		///
		void MiSaveClick(object sender, System.EventArgs e)
		{
			DoSave();
		}
		
		///
		/// <summary>
		/// Save All menu event handler
		/// </summary>
		///
		void MiSaveAllClick(object sender, System.EventArgs e)
		{
			DoSaveAllAsZip();
		}
		
		///
		/// <summary>
		/// Clear menu event handler
		/// </summary>
		///
		void MiClearClick(object sender, System.EventArgs e)
		{
			DoClear();
		}
		
		///
		/// <summary>
		/// Clear All menu event handler
		/// </summary>
		///
		void MiClearAllClick(object sender, System.EventArgs e)
		{
			DoClearAll();
		}
		
		///
		/// <summary>
		/// Pause menu event handler
		/// </summary>
		///
		void MiPauseClick(object sender, System.EventArgs e)
		{
			DoPause();
		}
		
		///
		/// <summary>
		/// Pause All menu event handler
		/// </summary>
		///
		void MiPauseAllClick(object sender, System.EventArgs e)
		{
			DoPauseAll();
		}
		
		///
		/// <summary>
		/// Unpause All menu event handler
		/// </summary>
		///
		void MiUnpauseAllClick(object sender, System.EventArgs e)
		{
			DoUnpauseAll();
		}
		
		///
		/// <summary>
		/// Reload menu event handler
		/// </summary>
		///
		void MiReloadClick(object sender, System.EventArgs e)
		{
			DoReload();
		}
		
		///
		/// <summary>
		/// Reload All menu event handler
		/// </summary>
		///
		void MiReloadAllClick(object sender, System.EventArgs e)
		{
			DoReloadAll();
		}
		
		///
		/// <summary>
		/// Reload Configuration File menu event handler
		/// </summary>
		///
		void MiReloadConfigurationFileClick(object sender, System.EventArgs e)
		{
			DoReloadConfigurationFile();
		}
		
		///
		/// <summary>
		/// Edit Configuration File menu event handler
		/// </summary>
		///
		void MiEditConfigurationFileClick(object sender, System.EventArgs e)
		{
			DoEditConfigurationFile();
		}
		
		///
		/// <summary>
		/// Open New Configuration File menu event handler
		/// </summary>
		///
		void MiOpenNewConfigurationFileClick(object sender, System.EventArgs e)
		{
			DoOpenNewConfigurationFile();
		}
		
		
		void MiFindClick(object sender, System.EventArgs e)
		{
			DoFind (true);
		}
		
		void MiFindPreviousClick(object sender, System.EventArgs e)
		{
			finder_i.SearchForwards = false;
			DoFind (false);
		}
		
		void MiFindNextClick(object sender, System.EventArgs e)
		{
			finder_i.SearchForwards = true;
			DoFind (false);
		}
		
		void MiFilterClick(object sender, System.EventArgs e)
		{
			miFilter.Checked = !miFilter.Checked;
			DoFilter(miFilter.Checked);
		}
				
		void MRUClick(object sender, string sFileName_p)
		{
			string sPathOnly = Path.GetDirectoryName(sFileName_p);
			
			if (null == sPathOnly  ||  0 == sPathOnly.Length)
			{
				sFileName_p = Path.Combine(Application.StartupPath, sFileName_p);
			}
			
			sConfigFileName_i = sFileName_p;
			DoReloadConfigurationFile();
		}
		
		
		void MiTipOfTheDayClick(object sender, System.EventArgs e)
		{
			TipOfTheDayForm f = new TipOfTheDayForm();
			f.ShowDialog();
			
		}
		
		void MiAboutClick(object sender, System.EventArgs e)
		{
			AboutForm f = new AboutForm();
			f.ShowDialog();
		}
		
		void MiPrettyPrintXMLClick(object sender, System.EventArgs e)
		{
			DoPrettyPrintXML();
		}
		
		void MiPrettyPrintJSONClick(object sender, System.EventArgs e)
		{
			DoPrettyPrintJSON();
		}
			
		
		void MiUnescapeQueryStringClick(object sender, System.EventArgs e)
		{
			DoUnescapeQueryString();
		}
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		///
		/// <summary>
		/// Creates and initialises the form's child controls.
		/// </summary>
		/// <remarks>
		/// Note that this does not create the child windows that display
		/// the logging information.
		/// </remarks>
		///
		void InitializeComponent() {
			this.components = new System.ComponentModel.Container();
			System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
			this.miClear = new System.Windows.Forms.MenuItem();
			this.miPrettyPrintJSON = new System.Windows.Forms.MenuItem();
			this.miReload = new System.Windows.Forms.MenuItem();
			this.miPause = new System.Windows.Forms.MenuItem();
			this.miPauseAll = new System.Windows.Forms.MenuItem();
			this.menuItem8 = new System.Windows.Forms.MenuItem();
			this.menuItem9 = new System.Windows.Forms.MenuItem();
			this.menuItem = new System.Windows.Forms.MenuItem();
			this.menuItem4 = new System.Windows.Forms.MenuItem();
			this.menuItem5 = new System.Windows.Forms.MenuItem();
			this.menuItem6 = new System.Windows.Forms.MenuItem();
			this.menuItem1 = new System.Windows.Forms.MenuItem();
			this.miTipOfTheDay = new System.Windows.Forms.MenuItem();
			this.menuItem18 = new System.Windows.Forms.MenuItem();
			this.miAbout = new System.Windows.Forms.MenuItem();
			this.menuItem2 = new System.Windows.Forms.MenuItem();
			this.menuItem3 = new System.Windows.Forms.MenuItem();
			this.miFilter = new System.Windows.Forms.MenuItem();
			this.menuItem16 = new System.Windows.Forms.MenuItem();
			this.miCopyAll = new System.Windows.Forms.MenuItem();
			this.miReloadAll = new System.Windows.Forms.MenuItem();
			this.miSave = new System.Windows.Forms.MenuItem();
			this.miEditConfigurationFile = new System.Windows.Forms.MenuItem();
			this.miUnescapeQueryString = new System.Windows.Forms.MenuItem();
			this.xxx = new System.Windows.Forms.MenuItem();
			this.miSaveAll = new System.Windows.Forms.MenuItem();
			this.miPrettyPrintXML = new System.Windows.Forms.MenuItem();
			this.miFindPrevious = new System.Windows.Forms.MenuItem();
			this.miTileVertically = new System.Windows.Forms.MenuItem();
			this.mEdit = new System.Windows.Forms.MenuItem();
			this.miCopy = new System.Windows.Forms.MenuItem();
			this.miClearAll = new System.Windows.Forms.MenuItem();
			this.miFind = new System.Windows.Forms.MenuItem();
			this.miFindNext = new System.Windows.Forms.MenuItem();
			this.miSep99 = new System.Windows.Forms.MenuItem();
			this.mView = new System.Windows.Forms.MenuItem();
			this.miUnpauseAll = new System.Windows.Forms.MenuItem();
			this.miClose = new System.Windows.Forms.MenuItem();
			this.mainMenu = new System.Windows.Forms.MainMenu(this.components);
			this.mFile = new System.Windows.Forms.MenuItem();
			this.miOpen = new System.Windows.Forms.MenuItem();
			this.menuItem20 = new System.Windows.Forms.MenuItem();
			this.menuItem23 = new System.Windows.Forms.MenuItem();
			this.miExit = new System.Windows.Forms.MenuItem();
			this.miOpenNewConfigurationFile = new System.Windows.Forms.MenuItem();
			this.menuItem14 = new System.Windows.Forms.MenuItem();
			this.miMRU = new System.Windows.Forms.MenuItem();
			this.menuItem17 = new System.Windows.Forms.MenuItem();
			this.menuItem19 = new System.Windows.Forms.MenuItem();
			this.mWindow = new System.Windows.Forms.MenuItem();
			this.miTileHorizonally = new System.Windows.Forms.MenuItem();
			this.miCascade = new System.Windows.Forms.MenuItem();
			this.miArrangeIcons = new System.Windows.Forms.MenuItem();
			this.menuItem7 = new System.Windows.Forms.MenuItem();
			this.miReloadConfigurationFile = new System.Windows.Forms.MenuItem();
			this.menuItem11 = new System.Windows.Forms.MenuItem();
			this.menuItem12 = new System.Windows.Forms.MenuItem();
			this.menuItem10 = new System.Windows.Forms.MenuItem();
			this.menuItem13 = new System.Windows.Forms.MenuItem();
			this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
			this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
			this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog();
			this.SuspendLayout();
			// 
			// miClear
			// 
			this.miClear.Index = 3;
			this.miClear.Shortcut = System.Windows.Forms.Shortcut.Del;
			this.miClear.Text = "C&lear";
			this.miClear.Click += new System.EventHandler(this.MiClearClick);
			// 
			// miPrettyPrintJSON
			// 
			this.miPrettyPrintJSON.Index = 12;
			this.miPrettyPrintJSON.Text = "Pretty Print Selected &JSON";
			this.miPrettyPrintJSON.Click += new System.EventHandler(this.MiPrettyPrintJSONClick);
			// 
			// miReload
			// 
			this.miReload.Index = 4;
			this.miReload.Shortcut = System.Windows.Forms.Shortcut.CtrlL;
			this.miReload.Text = "&Load Entire File";
			this.miReload.Click += new System.EventHandler(this.MiReloadClick);
			// 
			// miPause
			// 
			this.miPause.Index = 0;
			this.miPause.Shortcut = System.Windows.Forms.Shortcut.CtrlP;
			this.miPause.Text = "&Stop";
			this.miPause.Click += new System.EventHandler(this.MiPauseClick);
			// 
			// miPauseAll
			// 
			this.miPauseAll.Index = 1;
			this.miPauseAll.Shortcut = System.Windows.Forms.Shortcut.CtrlShiftP;
			this.miPauseAll.Text = "Pause &All Windows";
			this.miPauseAll.Click += new System.EventHandler(this.MiPauseAllClick);
			// 
			// menuItem8
			// 
			this.menuItem8.Index = -1;
			this.menuItem8.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
									this.menuItem9});
			this.menuItem8.MergeOrder = 1;
			this.menuItem8.Text = "fdgs";
			// 
			// menuItem9
			// 
			this.menuItem9.Index = 0;
			this.menuItem9.Text = "fds";
			// 
			// menuItem
			// 
			this.menuItem.Index = -1;
			this.menuItem.Text = "&Edit";
			// 
			// menuItem4
			// 
			this.menuItem4.Index = 0;
			this.menuItem4.Text = "fds";
			// 
			// menuItem5
			// 
			this.menuItem5.Index = -1;
			this.menuItem5.Text = "Save &All Windows...";
			this.menuItem5.Click += new System.EventHandler(this.MiSaveAllClick);
			// 
			// menuItem6
			// 
			this.menuItem6.Index = 2;
			this.menuItem6.Text = "-";
			// 
			// menuItem1
			// 
			this.menuItem1.Index = 4;
			this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
									this.miTipOfTheDay,
									this.menuItem18,
									this.miAbout});
			this.menuItem1.Text = "&Help";
			// 
			// miTipOfTheDay
			// 
			this.miTipOfTheDay.Index = 0;
			this.miTipOfTheDay.Text = "&Tip of the day";
			this.miTipOfTheDay.Click += new System.EventHandler(this.MiTipOfTheDayClick);
			// 
			// menuItem18
			// 
			this.menuItem18.Index = 1;
			this.menuItem18.Text = "-";
			// 
			// miAbout
			// 
			this.miAbout.Index = 2;
			this.miAbout.Text = "About Log Manager";
			this.miAbout.Click += new System.EventHandler(this.MiAboutClick);
			// 
			// menuItem2
			// 
			this.menuItem2.Index = -1;
			this.menuItem2.Text = "&Edit";
			// 
			// menuItem3
			// 
			this.menuItem3.Index = -1;
			this.menuItem3.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
									this.menuItem4});
			this.menuItem3.MergeOrder = 1;
			this.menuItem3.Text = "fdgs";
			// 
			// miFilter
			// 
			this.miFilter.Index = 10;
			this.miFilter.Shortcut = System.Windows.Forms.Shortcut.CtrlH;
			this.miFilter.Text = "F&ilter...";
			this.miFilter.Click += new System.EventHandler(this.MiFilterClick);
			// 
			// menuItem16
			// 
			this.menuItem16.Index = 5;
			this.menuItem16.Text = "-";
			// 
			// miCopyAll
			// 
			this.miCopyAll.Index = 1;
			this.miCopyAll.Shortcut = System.Windows.Forms.Shortcut.CtrlShiftC;
			this.miCopyAll.Text = "Copy E&ntire Window";
			this.miCopyAll.Click += new System.EventHandler(this.MiCopyAllClick);
			// 
			// miReloadAll
			// 
			this.miReloadAll.Index = 5;
			this.miReloadAll.Shortcut = System.Windows.Forms.Shortcut.CtrlShiftL;
			this.miReloadAll.Text = "Load &Entire File For All Windows";
			this.miReloadAll.Click += new System.EventHandler(this.MiReloadAllClick);
			// 
			// miSave
			// 
			this.miSave.Index = 3;
			this.miSave.Shortcut = System.Windows.Forms.Shortcut.CtrlS;
			this.miSave.Text = "&Save Current Window...";
			this.miSave.Click += new System.EventHandler(this.MiSaveClick);
			// 
			// miEditConfigurationFile
			// 
			this.miEditConfigurationFile.Index = 7;
			this.miEditConfigurationFile.Text = "&Edit this Configuration File";
			this.miEditConfigurationFile.Click += new System.EventHandler(this.MiEditConfigurationFileClick);
			// 
			// miUnescapeQueryString
			// 
			this.miUnescapeQueryString.Index = 13;
			this.miUnescapeQueryString.Text = "Unescape &QueryString";
			this.miUnescapeQueryString.Click += new System.EventHandler(this.MiUnescapeQueryStringClick);
			// 
			// xxx
			// 
			this.xxx.Index = 3;
			this.xxx.Shortcut = System.Windows.Forms.Shortcut.CtrlR;
			this.xxx.Text = "-";
			this.xxx.Click += new System.EventHandler(this.MUNUSEDClick);
			// 
			// miSaveAll
			// 
			this.miSaveAll.Index = 4;
			this.miSaveAll.Text = "Save &All Windows...";
			this.miSaveAll.Click += new System.EventHandler(this.MiSaveAllClick);
			// 
			// miPrettyPrintXML
			// 
			this.miPrettyPrintXML.Index = 11;
			this.miPrettyPrintXML.Text = "Pretty Print Selected &XML";
			this.miPrettyPrintXML.Click += new System.EventHandler(this.MiPrettyPrintXMLClick);
			// 
			// miFindPrevious
			// 
			this.miFindPrevious.Index = 7;
			this.miFindPrevious.Shortcut = System.Windows.Forms.Shortcut.F2;
			this.miFindPrevious.Text = "Find &Previous";
			this.miFindPrevious.Click += new System.EventHandler(this.MiFindPreviousClick);
			// 
			// miTileVertically
			// 
			this.miTileVertically.Index = 1;
			this.miTileVertically.Text = "Tile Vertically";
			this.miTileVertically.Click += new System.EventHandler(this.MiTileVerticallyClick);
			// 
			// mEdit
			// 
			this.mEdit.Index = 1;
			this.mEdit.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
									this.miCopy,
									this.miCopyAll,
									this.menuItem6,
									this.miClear,
									this.miClearAll,
									this.menuItem16,
									this.miFind,
									this.miFindPrevious,
									this.miFindNext,
									this.miSep99,
									this.miFilter,
									this.miPrettyPrintXML,
									this.miPrettyPrintJSON,
									this.miUnescapeQueryString});
			this.mEdit.Text = "&Edit";
			// 
			// miCopy
			// 
			this.miCopy.Index = 0;
			this.miCopy.Shortcut = System.Windows.Forms.Shortcut.CtrlC;
			this.miCopy.Text = "&Copy";
			this.miCopy.Click += new System.EventHandler(this.MiCopyClick);
			// 
			// miClearAll
			// 
			this.miClearAll.Index = 4;
			this.miClearAll.Shortcut = System.Windows.Forms.Shortcut.CtrlDel;
			this.miClearAll.Text = "Clea&r All Windows";
			this.miClearAll.Click += new System.EventHandler(this.MiClearAllClick);
			// 
			// miFind
			// 
			this.miFind.Index = 6;
			this.miFind.Shortcut = System.Windows.Forms.Shortcut.CtrlF;
			this.miFind.Text = "&Find...";
			this.miFind.Click += new System.EventHandler(this.MiFindClick);
			// 
			// miFindNext
			// 
			this.miFindNext.Index = 8;
			this.miFindNext.Shortcut = System.Windows.Forms.Shortcut.F3;
			this.miFindNext.Text = "Find &Next";
			this.miFindNext.Click += new System.EventHandler(this.MiFindNextClick);
			// 
			// miSep99
			// 
			this.miSep99.Index = 9;
			this.miSep99.Text = "-";
			this.miSep99.Click += new System.EventHandler(this.MiFilterClick);
			// 
			// mView
			// 
			this.mView.Index = 2;
			this.mView.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
									this.miPause,
									this.miPauseAll,
									this.miUnpauseAll,
									this.xxx,
									this.miReload,
									this.miReloadAll});
			this.mView.Text = "&View";
			// 
			// miUnpauseAll
			// 
			this.miUnpauseAll.Index = 2;
			this.miUnpauseAll.Shortcut = System.Windows.Forms.Shortcut.CtrlShiftU;
			this.miUnpauseAll.Text = "Sta&rt All Windows";
			this.miUnpauseAll.Click += new System.EventHandler(this.MiUnpauseAllClick);
			// 
			// miClose
			// 
			this.miClose.Index = 1;
			this.miClose.Text = "&Close Current Log File";
			this.miClose.Click += new System.EventHandler(this.MiCloseClick);
			// 
			// mainMenu
			// 
			this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
									this.mFile,
									this.mEdit,
									this.mView,
									this.mWindow,
									this.menuItem1});
			// 
			// mFile
			// 
			this.mFile.Index = 0;
			this.mFile.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
									this.miOpen,
									this.miClose,
									this.menuItem20,
									this.miSave,
									this.miSaveAll,
									this.menuItem23,
									this.miExit,
									this.miEditConfigurationFile,
									this.miOpenNewConfigurationFile,
									this.menuItem14,
									this.miMRU,
									this.menuItem17,
									this.menuItem19});
			this.mFile.Text = "&File";
			// 
			// miOpen
			// 
			this.miOpen.Index = 0;
			this.miOpen.Shortcut = System.Windows.Forms.Shortcut.CtrlO;
			this.miOpen.Text = "&Open a Single Log File...";
			this.miOpen.Click += new System.EventHandler(this.MiOpenClick);
			// 
			// menuItem20
			// 
			this.menuItem20.Index = 2;
			this.menuItem20.Text = "-";
			// 
			// menuItem23
			// 
			this.menuItem23.Index = 5;
			this.menuItem23.Text = "-";
			// 
			// miExit
			// 
			this.miExit.Index = 6;
			this.miExit.Shortcut = System.Windows.Forms.Shortcut.CtrlShiftR;
			this.miExit.Text = "&Re-open All Windows";
			this.miExit.Click += new System.EventHandler(this.MiReloadConfigurationFileClick);
			// 
			// miOpenNewConfigurationFile
			// 
			this.miOpenNewConfigurationFile.Index = 8;
			this.miOpenNewConfigurationFile.Text = "Open a &Different Configuration File...";
			this.miOpenNewConfigurationFile.Click += new System.EventHandler(this.MiOpenNewConfigurationFileClick);
			// 
			// menuItem14
			// 
			this.menuItem14.Index = 9;
			this.menuItem14.Text = "-";
			// 
			// miMRU
			// 
			this.miMRU.Index = 10;
			this.miMRU.Text = "MRU";
			// 
			// menuItem17
			// 
			this.menuItem17.Index = 11;
			this.menuItem17.Text = "-";
			// 
			// menuItem19
			// 
			this.menuItem19.Index = 12;
			this.menuItem19.Text = "E&xit";
			this.menuItem19.Click += new System.EventHandler(this.MiExitClick);
			// 
			// mWindow
			// 
			this.mWindow.Index = 3;
			this.mWindow.MdiList = true;
			this.mWindow.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
									this.miTileHorizonally,
									this.miTileVertically,
									this.miCascade,
									this.miArrangeIcons});
			this.mWindow.Text = "&Window";
			// 
			// miTileHorizonally
			// 
			this.miTileHorizonally.Index = 0;
			this.miTileHorizonally.Text = "Tile Horizontally";
			this.miTileHorizonally.Click += new System.EventHandler(this.MiTileHorizonallyClick);
			// 
			// miCascade
			// 
			this.miCascade.Index = 2;
			this.miCascade.Text = "Cascade";
			this.miCascade.Click += new System.EventHandler(this.MiCascadeClick);
			// 
			// miArrangeIcons
			// 
			this.miArrangeIcons.Index = 3;
			this.miArrangeIcons.Text = "Arrange Icons";
			this.miArrangeIcons.Click += new System.EventHandler(this.MiArrangeIconsClick);
			// 
			// menuItem7
			// 
			this.menuItem7.Index = -1;
			this.menuItem7.Text = "fds";
			// 
			// miReloadConfigurationFile
			// 
			this.miReloadConfigurationFile.Index = -1;
			this.miReloadConfigurationFile.Text = "Open &New Configuration File";
			// 
			// menuItem11
			// 
			this.menuItem11.Index = -1;
			this.menuItem11.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
									this.menuItem12});
			this.menuItem11.MergeOrder = 1;
			this.menuItem11.Text = "fdgs";
			// 
			// menuItem12
			// 
			this.menuItem12.Index = 0;
			this.menuItem12.Text = "fds";
			// 
			// menuItem10
			// 
			this.menuItem10.Index = -1;
			this.menuItem10.Text = "fds";
			// 
			// menuItem13
			// 
			this.menuItem13.Index = -1;
			this.menuItem13.Text = "fds";
			// 
			// openFileDialog1
			// 
			this.openFileDialog1.FileName = "openFileDialog1";
			// 
			// MainForm
			// 
			this.AllowDrop = true;
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(680, 666);
			this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
			this.IsMdiContainer = true;
			this.Menu = this.mainMenu;
			this.Name = "MainForm";
			this.Text = "Log Manager";
			this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
			this.Closing += new System.ComponentModel.CancelEventHandler(this.CreatedFormClosing);
			this.Closed += new System.EventHandler(this.CreatedFormClosed);
			this.Load += new System.EventHandler(this.CreatedFormLoad);
			this.MdiChildActivate += new System.EventHandler(this.CreatedFormMdiChildActivate);
			this.DragDrop += new System.Windows.Forms.DragEventHandler(this.MainFormDragDrop);
			this.DragEnter += new System.Windows.Forms.DragEventHandler(this.MainFormDragEnter);
			this.ResumeLayout(false);
		}
		private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1;
		private System.Windows.Forms.SaveFileDialog saveFileDialog1;
		private System.Windows.Forms.OpenFileDialog openFileDialog1;
		private System.ComponentModel.IContainer components;
		
		
		
		
		
		
		
		///
		/// <summary>
		/// Allows the user to open an existing file as a new log window.
		/// </summary>
		/// <remarks>
		/// Presents the user with an 'Open File' dialog box and allows them
		/// to specify one or more files to open.  A new <code>LoggingBaseForm</code> object
		/// will be created for each file.
		/// </remarks>
		///
		public void DoOpen()
		
		{			
			//OpenFileDialog oDialog = new OpenFileDialog();			
			//openFileDialog1.InitialDirectory = "C:\\";
			openFileDialog1.Filter = "All files (*.*)|*.*";
			openFileDialog1.Multiselect = true;
			if (DialogResult.OK == openFileDialog1.ShowDialog())
			{
				DoOpen(openFileDialog1.FileNames);
			}
		}
		
		
		
		
		///
		/// <summary>
		/// Opens an existing file as a new log window.
		/// </summary>
		/// <remarks>
		/// A new <code>LoggingBaseForm</code> object will be created for each file.
		/// </remarks>
		///
		public void DoOpen(string[] vFileNames_p)
		{
			AddFilesToLogset (vFileNames_p);
			
			// Before we create any new forms, make sure that the windows are tiled,
			// otherwise we get odd behaviour whereby the rich text control doesn't
			// resize with the form.
			this.LayoutMdi(MdiLayout.TileHorizontal);
			
			foreach (string sFile in vFileNames_p)
			{
				try
				{
					logsetLogfile file = new logsetLogfile();
					file.autoLogin = new logsetLogfileAutoLogin[0];
					file.match = new logsetLogfileMatch[0];
					file.name = GetUniqueName(Path.GetFileName (sFile));
					file.path = sFile;
					
					LogsetWithFile set = LogsetLoader.LoadLogsetFromFile(sConfigFileName_i);
					LoggingBaseForm form = LoggingFormFactory.CreateForm(file, set.Logset);
					
					form.MdiParent = this;					
					form.Show();			
				}
				catch (IOException ioe)
				{
					LogError ("DoOpen", "Error opening file <" + sFile + ">\n\n" + ioe.Message, ioe);
				}
			}
		}
		
		
		
		
		///
		/// <summary>
		/// Asks the user whether they want the given log files to be added
		/// to the current 'configuration' logset file.
		/// </summary>
		/// <remarks>
		/// Any errors here will be reported but not passed up to the calling
		/// method.  It returns true if the files were added successfully or
		/// false if there was an error or the user declined.
		/// </remarks>
		///
		private bool AddFilesToLogset (string[] vFileNames_p)
		{
			// 
			// Build up a question to ask them.
			//
			string sMessage;
			
			if (vFileNames_p.Length > 1)
			{
				sMessage = "After I open these files, do you want to add them to the current configuration so they open next time as well? \n";
			}
			else
			{
				sMessage = "After I open this file, do you want to add it to the current configuration so it opens next time as well? \n";
			}
			
			foreach (string sFile in vFileNames_p)
			{
				sMessage += "\n    " + sFile;
			}
			
			//
			// Ask the question and bomb out if they say "no"
			//
			if (DialogResult.No == MessageBox.Show(sMessage,
			                                       this.Text,
			                                       MessageBoxButtons.YesNo,
			                                       MessageBoxIcon.Question))
			{
				return false;
			}
			
			//
			// Now load the logset and add these files to it.
			//
			LogsetWithFile set = LogsetLoader.LoadLogsetFromFile(sConfigFileName_i);
			
			IList newFiles = new ArrayList();
			
			foreach (string sFile in vFileNames_p)
			{
				logsetLogfile file = new logsetLogfile();
				file.autoLogin = new logsetLogfileAutoLogin[0];
				file.match = new logsetLogfileMatch[0];
				file.name = GetUniqueName(Path.GetFileName (sFile));
				file.path = sFile;
				
				newFiles.Add (file);
			}
			
			//
			// Create a copy of the existing array of log files...
			//
			int iOldSize = set.Logset.logfile.Length;
			int iNewSize = iOldSize + newFiles.Count;
			logsetLogfile[] allFiles = new logsetLogfile[iNewSize];
			Array.Copy(set.Logset.logfile, allFiles, iOldSize);
			
			
			//
			// ...and add these new ones.
			//
			for (int i=0; i<newFiles.Count; i++)
			{
				logsetLogfile newFile = (logsetLogfile) newFiles[i];
				allFiles[iOldSize + i] = newFile;
			}
			
			//
			// Save the logset
			//
			try
			{
				set.Logset.logfile = allFiles;
				LogsetLoader.SaveLogsetWithFile(set);
				MessageBox.Show ("Saved");
				return true;
			}
			catch (Exception ex)
			{
				LogError ("AddFilesToLogset", "Couldn't save new configuration file, sorry!\n" + ex.Message, ex);
				return false;
			}
		}
		
		
		///
		/// <summary>
		/// Attempts to close the current child logging window.
		/// </summary>
		/// <remarks>
		/// If there is an active <code>LoggingBaseForm</code> MDI child window then it will
		/// be closed.
		/// </remarks>
		///
		public void DoClose()
		{
			if (null != this.ActiveMdiChild)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) this.ActiveMdiChild;
				if (oChild.DoClose(false))
				{
					this.RemoveOwnedForm(oChild);
				}
			}
		}
		
		
		///
		/// <summary>
		/// Allows the user to save the contents of the current window.
		/// </summary>
		/// <remarks>
		/// Presents the user with a 'Save File' dialog box, allowing them to specify a path for the
		/// output file.  The contents of the active <code>LoggingBaseForm</code> window will be saved
		/// to this file in text format.
		/// </remarks>
		/// 
		public void DoSave()
		{
			if (null != this.ActiveMdiChild)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) this.ActiveMdiChild;
				//SaveFileDialog oDialog = new SaveFileDialog();
				saveFileDialog1.Filter = "Text files (*.txt)|*.txt|All Files (*.*)|*.*";
				String sFile = oChild.Name + ".txt";
				saveFileDialog1.OverwritePrompt = true;
				saveFileDialog1.FileName = sFile;
				
				if (DialogResult.OK == saveFileDialog1.ShowDialog())
				{
					sFile = saveFileDialog1.FileName;					
					
					try
					{
						oChild.DoSave(sFile);
					}
					catch (Exception e)
					{						
						LogError ("DoSave", "Error saving file: " + e.Message, e);
					}
				}
			}
		}
		
		
		///
		/// <summary>
		/// Allows the user to save the contents of the all current windows.
		/// </summary>
		/// <remarks>
		/// Presents the user with a 'Choose Folder' dialog box, allowing them to specify a parent path for the
		/// output files.  The contents of each <code>LoggingBaseForm</code> window will be saved
		/// into files within this directory.  The files are saved using the log windows' titles with a '.txt'
		/// file extension.
		/// This functionality has now been superseded by the DoSaveAllAsZip method.
		/// </remarks>
		/// 
		public void DoSaveAll()
		{
			//FolderBrowserDialog oDialog = new FolderBrowserDialog();
			
			if (DialogResult.OK != folderBrowserDialog1.ShowDialog()) return;
			
			String sFolderName = folderBrowserDialog1.SelectedPath;
			
			if (!sFolderName.EndsWith ("\\"))
			{
				sFolderName += "\\";
			}
			
			bool bExistingFiles = false;
			
			foreach (Form oForm in this.MdiChildren)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) oForm;
				String sFile = oChild.Name + ".txt";
				
				if (System.IO.File.Exists (sFolderName + sFile))
				{
					bExistingFiles = true;
					break;
				}
			}
			
			bool bDirectoryCreated = false;
			
			if (bExistingFiles)
			{
				DialogResult oResult = MessageBox.Show ("There are files with the same name in this directory.\nDo you want to create a new sub-directory?  (Clicking 'No' will overwrite the existing files)", this.Text, MessageBoxButtons.YesNoCancel);
				
				if (DialogResult.Yes == oResult)
				{
					//
					// Create a new directory
					//
					sFolderName += "Logs " + System.DateTime.Now.Day + "-" +
						System.DateTime.Now.Month + "-" +
						System.DateTime.Now.Year + " " +
						TwoDigits(System.DateTime.Now.Hour) + "." +
						TwoDigits(System.DateTime.Now.Minute) + "." +
						TwoDigits(System.DateTime.Now.Second) + "\\";
					
					try
					{
						Directory.CreateDirectory(sFolderName);
						bDirectoryCreated = true;
					}
					catch (IOException ioe)
					{
						LogError ("DoSaveAll", "Failed to create directory <" + sFolderName + ">", ioe);
						return;
					}
				}
				else if (DialogResult.Cancel == oResult)
				{
					return;
				}
			}
			
			//
			// Now do the actual saving
			//
			bool bFilesSaved = false;
			
			foreach (Form oForm in this.MdiChildren)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) oForm;
				try
				{
					oChild.DoSave (sFolderName + oChild.Name + ".txt");
					bFilesSaved = true;	
				}
				catch (Exception e)
				{
					LogError ("DoSaveAll", "Couldn't save file <" + oChild.Name + ".txt>", e);
				}							
			}
			
			if (bDirectoryCreated  &&  bFilesSaved)
			{
				MessageBox.Show ("Log files saved in directory <" + sFolderName + ">");
			}
		}
		
		
		
		
		
		
		
		
		///
		/// <summary>
		/// Allows the user to save the contents of the all current windows in a single zip file.
		/// </summary>
		/// <remarks>
		/// Presents the user with a 'Save As...' dialog box, allowing them to choose a name and directory
		/// for the output zip file.  The contents of each <code>LoggingBaseForm</code> window will be saved
		/// into text files within this zip file.  The files are saved using the log windows' titles with a
		/// '.txt' file extension.
		/// </remarks>
		/// 
		public void DoSaveAllAsZip()
		{
			//SaveFileDialog dialog = new SaveFileDialog();
			
			saveFileDialog1.AddExtension = true;
			saveFileDialog1.DefaultExt = ".zip";
			//saveFileDialog1.InitialDirectory = System.IO.Directory.GetCurrentDirectory();
			saveFileDialog1.FileName = GetDefaultZipFileName(saveFileDialog1.InitialDirectory);
			saveFileDialog1.Filter = "Zip files (*.zip)|*.zip|All files (*.*)|*.*";
			saveFileDialog1.FilterIndex = 1;
			saveFileDialog1.Title = "Save All As Zip";
			
			if (DialogResult.OK != saveFileDialog1.ShowDialog()) return;
			
			String sZipFileName = saveFileDialog1.FileName;
			
			ZipOutputStream zipStream = null;
			
			try
			{
				zipStream = new ZipOutputStream(File.Create(sZipFileName));
			}
			catch (IOException ioe)
			{
				LogError ("DoSaveAllAsZip", "Couldn't create Zip file " + sZipFileName, ioe);
			}
			
			zipStream.SetLevel(DEFAULT_ZIP_LEVEL);
			
			//
			// Now do the actual saving
			//
			bool bFilesSaved = false;
			
			foreach (Form form in this.MdiChildren)
			{
				LoggingBaseForm child = (LoggingBaseForm) form;
				
				ZipEntry entry = new ZipEntry(child.Name + ".txt");
				zipStream.PutNextEntry(entry);
				
				if (!child.DumpText (zipStream))
				{
					LogError ("DoSaveAllAsZip", "Couldn't save file <" + child.Name + ">");
				}
				else
				{
					bFilesSaved = true;
				}
			}
			
			zipStream.Finish();
			zipStream.Close();
			
			if (bFilesSaved)
			{
				MessageBox.Show ("Log files saved as <" + sZipFileName + ">");
			}
		}
		
		
		
		private string GetDefaultZipFileName(string sDirectory_p)
		{
			string sName = String.Format("Logs {0:dd-MMM-yyyy}", System.DateTime.Now);
			
			if (! sDirectory_p.EndsWith ("\\"))  sDirectory_p += "\\";
			
			//MessageBox.Show ("Checking if file exists <" + sDirectory_p + sName + ".zip" + ">");
			
			if (File.Exists(sDirectory_p + sName + ".zip"))
			{
				for (int i = 2; i < 1000; i++)
				{
					string sNumberedName = sName + " (" + i + ")";
					
					if (! File.Exists (sDirectory_p + sNumberedName + ".zip"))
					{
						return sNumberedName;
					}
				}
			}
			
			return sName;
		}
		
		
		
		
		
		
		///
		/// <summary>
		/// Copies the selection of the current <code>LoggingBaseForm</code> window.
		/// </summary>
		/// 
		public void DoCopy (bool bSelectionOnly)
		{
			
			if (null != this.ActiveMdiChild)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) this.ActiveMdiChild;
				oChild.DoCopy (bSelectionOnly);
			}
		}
		
		
		
		///
		/// <summary>
		/// Copies the entire contents of the current <code>LoggingBaseForm</code> window.
		/// </summary>
		/// 
		public void DoCopyAll()
		{
			if (null != this.ActiveMdiChild)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) this.ActiveMdiChild;
				oChild.DoCopy (false);
			}
		}
		
		
		///
		/// <summary>
		/// Clears the contents of the current <code>LoggingBaseForm</code> window.
		/// </summary>
		/// 
		public void DoClear()
		{
			if (null != this.ActiveMdiChild)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) this.ActiveMdiChild;
				oChild.DoClear();
			}
		}
		
		
		///
		/// <summary>
		/// Clears the contents of all the <code>LoggingBaseForm</code> windows.
		/// </summary>
		/// 
		public void DoClearAll()
		{
			foreach (Form oForm in this.MdiChildren)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) oForm;
				oChild.DoClear();
			}
		}
		
		
		
		
		///
		/// <summary>
		/// Performs a search in the current active log file window using the current
		/// search settings.  If no match was found, a message box will be displayed
		/// to the user.
		/// </summary>
		/// <returns>True if a match was found, or the action was cancelled by the user</returns>
		/// 
		public bool DoFind(bool bShowForm_p)
		{
			if (null == this.ActiveMdiChild) return false;
			
			LoggingBaseForm child = (LoggingBaseForm) this.ActiveMdiChild;
			
			bool bFound = child.DoFind (finder_i, bShowForm_p);
			
			if (! bFound)
			{
				MessageBox.Show ("Not found: <" + finder_i.Pattern + ">",
				                 "Log Manager",
				                 MessageBoxButtons.OK);
			}
			
			return bFound;
		}
		
		
		
		
		///
		/// <summary>
		/// Gets filter information from the user and performs filtering on the current log window.
		/// </summary>
		/// <param name="bEnable_p">True if we want to turn filtering ON</param>
		/// 
		public void DoFilter (bool bEnable_p)
		{
			if (null == this.ActiveMdiChild) return;
			
			LoggingBaseForm child = (LoggingBaseForm) this.ActiveMdiChild;
			
			child.DoFilter(bEnable_p);
			
			miFilter.Checked = child.Filtered;
		}
		
		
		
		/// <summary>
		/// Reformats the selected XML text on the current log window
		/// </summary>
		public void DoPrettyPrintXML()
		{
			if (null == this.ActiveMdiChild) return;
			
			LoggingBaseForm child = (LoggingBaseForm) this.ActiveMdiChild;
			
			child.DoPrettyPrintSelectedXML();
		}
		
		
		
		
		/// <summary>
		/// Reformats the selected JSON text on the current log window
		/// </summary>
		public void DoPrettyPrintJSON()
		{
			if (null == this.ActiveMdiChild) return;
			
			LoggingBaseForm child = (LoggingBaseForm) this.ActiveMdiChild;
			
			child.DoPrettyPrintSelectedJSON();
		}
				
		
		
		/// <summary>
		/// Replaces any "%xx" and "+" encoding on the given string, similar to JavaScript's
		/// unescape() function.
		/// </summary>
		public void DoUnescapeQueryString()
		{
			if (null == this.ActiveMdiChild) return;
			
			LoggingBaseForm child = (LoggingBaseForm) this.ActiveMdiChild;
			
			child.DoUnescapeSelectedQueryString();
		}
		
		
		
		
		///
		/// <summary>
		/// Toggles the 'paused' state of the current <code>LoggingBaseForm</code> window.
		/// </summary>
		/// 
		public void DoPause()
		{
			if (null != this.ActiveMdiChild)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) this.ActiveMdiChild;
				if (oChild.Started)
				{
					oChild.DoStop();
					miPause.Text = "Un&pause";
				}
				else
				{
					oChild.DoStart();
					miPause.Text = "&Pause";
				}
			}
		}
		
		
		///
		/// <summary>
		/// Pauses all the <code>LoggingBaseForm</code> windows.
		/// </summary>
		/// 
		public void DoPauseAll()
		{
			foreach (Form oForm in this.MdiChildren)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) oForm;
				if (oChild.Started)
				{
					oChild.DoStop();
				}
			}
			
			miPause.Text = "Res&tart";
		}
		
		
		///
		/// <summary>
		/// Unpauses all the <code>LoggingBaseForm</code> windows.
		/// </summary>
		/// 
		public void DoUnpauseAll()
		{
			foreach (Form oForm in this.MdiChildren)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) oForm;
				if (!oChild.Started)
				{
					oChild.DoStart();
				}
			}
			
			miPause.Text = "&Pause";
		}
		
		
		///
		/// <summary>
		/// Presents a warning prompt to the user and reloads the text in the current <code>LoggingBaseForm</code> window.
		/// </summary>
		/// 
		public void DoReload()
		{
			if (null != this.ActiveMdiChild)
			{
				DialogResult oResult = MessageBox.Show ("This might take a while.  Do you want to do pattern matching on the file as well?", this.Text, MessageBoxButtons.YesNoCancel);
				
				if (DialogResult.Cancel != oResult)
				{
					LoggingBaseForm oChild = (LoggingBaseForm) this.ActiveMdiChild;
					oChild.DoReload(DialogResult.Yes == oResult);
				}
			}
		}
		
		
		///
		/// <summary>
		/// Presents a warning prompt to the user and reloads the text in all the <code>LoggingBaseForm</code> windows.
		/// </summary>
		/// 
		public void DoReloadAll()
		{
			DialogResult oResult = DialogResult.No;
			
			if (null != this.ActiveMdiChild)
			{
				oResult = MessageBox.Show ("This might take a while.  Do you want to do pattern matching on the files as well?", this.Text, MessageBoxButtons.YesNoCancel);
				if (DialogResult.Cancel == oResult) return;
			}
			
			foreach (Form oForm in this.MdiChildren)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) oForm;
				oChild.DoReload(DialogResult.Yes == oResult);
			}
		}
		
		
		
		///
		/// <summary>
		/// Sets the text of the Pause menu item depending on the paused state of the current <code>LoggingBaseForm</code> window.
		/// </summary>
		/// 
		public void DoMdiChildActivate()
		{
			if (null != this.ActiveMdiChild)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) this.ActiveMdiChild;
				if (oChild.Started)
				{
					miPause.Text = "&Pause";
				}
				else
				{
					miPause.Text = "Res&tart";
				}
			}
		}
		
		
		
		///
		/// <summary>
		/// Re-reads the configuration file
		/// </summary>
		/// <remarks>
		/// This method closes all of the open <code>LoggingBaseForm</code> windows and
		/// re-reads the configuration file, opening new child windows as necessary.
		/// </remarks>
		/// 
		public void DoReloadConfigurationFile()
		{
			foreach (Form oForm in this.MdiChildren)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) oForm;
				oChild.DoClose(true);
				this.RemoveOwnedForm(oChild);
			}
			
			System.Threading.Thread.Sleep(1500);
			
			InitLogs(sConfigFileName_i);
		}
		
		
		
		
		
		
		///
		/// <summary>
		/// Launches the current configuration file in its default editor.
		/// </summary>
		/// 
		public void DoEditConfigurationFile()
		{
			//System.Diagnostics.Process.Start(sConfigFileName_i);
			
			LogsetWithFile lwf = LogsetLoader.LoadLogsetFromFile (sConfigFileName_i);
			EditLogsetForm f = new EditLogsetForm(lwf);
			f.ShowDialog();
			
			if (!f.WasCancelled)
			{
				if (DialogResult.Yes == MessageBox.Show ("Do you want to refresh all the log windows now?", this.Text, MessageBoxButtons.YesNo))
				{
					DoReloadConfigurationFile();
				}
			}
		}
		
		
		
		
		
		
		
		
		///
		/// <summary>
		/// Re-initialises the application using a new configuration file.
		/// </summary>
		/// <remarks>
		/// This method prompts the user for a new configuration file to use
		/// and, if one is provided, closes all current child windows and
		/// creates new ones as necessary from the new configuration file.
		/// </remarks>
		/// 
		public void DoOpenNewConfigurationFile()
		{
			LogsetManagerForm manager = new LogsetManagerForm();
			manager.ShowDialog();
			
			if (null == manager.SelectedLogset) return;
			
			string sConfigFileName = manager.SelectedLogset.FileName;
			
			if (! Path.IsPathRooted (sConfigFileName))
			{
				sConfigFileName = Application.StartupPath + "\\" + sConfigFileName;
			}
			
			sConfigFileName_i = sConfigFileName;
			DoReloadConfigurationFile();
		}
		
		
		
		
		///
		/// <summary>
		/// Provides a way to make a given child form the active MDI child.
		/// </summary>
		/// 
		public void ActivateChild (Form oChild)
		{
			this.ActivateMdiChild(oChild);
		}
		
		
		
		///
		/// <summary>
		/// Re-initialises the application using a new configuration file.
		/// </summary>
		/// <remarks>
		/// This method prompts the user for a new configuration file to use
		/// and, if one is provided, closes all current child windows and
		/// creates new ones as necessary from the new configuration file.
		/// </remarks>
		/// 
		private void InitLogs(String sConfigFileName_p)
		{
			Log.Debug("InitLogs: reloading log file from <" + sConfigFileName_p + ">");
			
			logset oConfigFile = null;
			
			if (! System.IO.File.Exists (sConfigFileName_p))
			{
				LogError("InitLogs", "Config file not found: " + sConfigFileName_p + "\n");
				return;
			}
			
			//================================================================
			// Try to read in the configuration file
			//================================================================
			try
			{
				oConfigFile = LoadLogsetFromFile (sConfigFileName_p);
			}
			catch (Exception e)
			{
				LogError ("InitLogs", "Error parsing logset file:\n" + e.Message, e);
				return;
			}
			
			//================================================================
			// Process each 'log file' setting in the config file
			//================================================================
			EnsureUniqueNames (oConfigFile);
			
			
			//=================================================================
			// Open the logfiles in parallel
			//=================================================================
			ParallelRunner runner = new ParallelRunner();
			
			foreach (logsetLogfile file in oConfigFile.logfile)
			{
				runner.AddProcess (new LogsetOpenProcess(file, oConfigFile));
			}
			
			runner.RunAll();
			//MessageBox.Show ("Done running");
			
			//=================================================================
			// Activate any forms that were created
			//=================================================================
			foreach (Form form in runner.Results.Values)
			{
				if (null != form)
				{
					form.MdiParent = this;
					form.Show();
				}
			}
			
			
			//=================================================================
			// Display any exceptions that were generated
			//=================================================================
			foreach (string sName in runner.Exceptions.Keys)
			{
				Exception e = (Exception) runner.Exceptions[sName];
				MessageBox.Show ("Error opening file '" + sName + "'.\n\n" + e.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			
			
			
			
			
			this.LayoutMdi(MdiLayout.TileHorizontal);
			
			string sTitle = Path.GetFileNameWithoutExtension (sConfigFileName_p);
			
			this.Text = "Log Manager - " + sTitle;
			
			
			if (Path.GetDirectoryName(sConfigFileName_p) == Application.StartupPath)
			{
				// We want to make this as short as possible - leave off the path info
				mruList_i.AddFile(Path.GetFileName(sConfigFileName_p));
			}
			else
			{
				mruList_i.AddFile(sConfigFileName_p);
			}
		}
		
		
		
		
		
		private logset LoadLogsetFromFile(String sConfigFileName_p)
		{
			//================================================================
			// Get the XML schema from the local directory if possible
			//================================================================
			String sSchemaFileLoc = Application.StartupPath + "\\logs.xsd";
			
			if (System.IO.File.Exists (sSchemaFileLoc))
			{
				System.IO.Stream schemaStream = File.OpenRead(sSchemaFileLoc);
				System.Xml.XmlReader schemaReader = new System.Xml.XmlTextReader(schemaStream);
				
				return (logset) XmlUtils.DeserialiseFileWithValidation(typeof(logset), sConfigFileName_p, schemaReader);
			}
			else
			{
				MessageBox.Show("Warning: couldn't find the logs.xsd schema file in " + sSchemaFileLoc, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
				return (logset) XmlUtils.DeserialiseFile(typeof(logset), sConfigFileName_p);
			}
		}
		
		
		///
		/// <summary>
		/// Utility function to convert a number to a 2-digit string.
		/// </summary>
		/// 
		private String TwoDigits(int iValue)
		{
			if (iValue < 10)
			{
				return "0" + iValue.ToString();
			}
			else
			{
				return iValue.ToString();
			}
		}
		
		
		
		private void EnsureUniqueNames (logset logset_p)
		{
			Hashtable existingNames = new Hashtable();
			
			foreach (logsetLogfile file in logset_p.logfile)
			{
				string sName = file.name;
				int iSuffix = 2;
				
				while (existingNames.ContainsKey(sName))
				{
					sName = file.name + " (" + iSuffix + ")";
					iSuffix++;
				}
				
				// Ensure the unique filename is remembered.
				file.name = sName;
				
				existingNames.Add(sName, sName);
			}
		}
		
		
		///
		/// <summary>
		/// Utility function to find a unique child window name.
		/// </summary>
		/// <remarks>
		/// This method attempts to create a unique window caption by appending a number
		/// between 0 and 10000.
		/// </remarks>
		/// 
		private String GetUniqueName (String sName_p)
		{
			if (IsUniqueName (sName_p))  return sName_p;
			
			sName_p += " - ";
			
			for (int i = 0; i<10000; i++)
			{
				if (IsUniqueName (sName_p + i.ToString()))
				{
					return sName_p + i.ToString();
				}
			}
			
			throw new System.IO.IOException ("Unable to find a unique name for <" + sName_p + ">");
		}
		
		
		
		
		///
		/// <summary>
		/// Utility function to check for child window name conflicts.
		/// </summary>
		/// <remarks>
		/// This method checks the name of each child window to make sure it
		/// doesn't conflict the proposed name <code>sName_p</code>
		/// </remarks>
		/// 
		private bool IsUniqueName (String sName_p)
		{
			foreach (Form oForm in this.MdiChildren)
			{
				LoggingBaseForm oChild = (LoggingBaseForm) oForm;
				if (sName_p.Equals(oChild.Name))
				{
					return false;
				}
			}
			
			return true;
		}
		
		
		private static void SetupDebugLog()
		{
			int iLogIndex = 0;
			
			while (iLogIndex < 10)
			{
				string sLogFile;
				
				if (0 == iLogIndex)
				{
					sLogFile = "lmdebug.txt";
				}
				else
				{
					sLogFile = "lmdebug." + iLogIndex + ".txt";
				}
				
				try
				{
					System.Diagnostics.TextWriterTraceListener trl = new System.Diagnostics.TextWriterTraceListener(sLogFile);
					System.Diagnostics.Debug.Listeners.Add(trl);
					break;
				}
				catch (Exception ex)
				{
					iLogIndex++;
				}
			}
		}
		
		
		protected static void LogError (String sMethod_p, String sText_p)
		{
			LogError (sMethod_p, sText_p, null);
		}
		
		protected static void LogError (String sMethod_p, String sText_p, Exception exception_p)
		{
			if (null != exception_p)
			{
				
				Log.Error ("ERROR in " + sMethod_p + ": " + sText_p, exception_p);
			}
			else
			{
				Log.Error ("ERROR in " + sMethod_p + ": " + sText_p);
			}
			MessageBox.Show (sText_p, "Log Manager", MessageBoxButtons.OK, MessageBoxIcon.Error);
		}
		
		
		
		
	}
	
	
	
	/// <summary>
	/// Allows logsets to be opened in parallel.  Care must be taken beforehand
	/// to ensure that each logsetLogfile that is used with this class has a
	/// unique name.
	/// </summary>
	internal class LogsetOpenProcess : ParallelProcess
	{
		protected logsetLogfile file_i;
		protected logset configFile_i;
		
		
		public LogsetOpenProcess (logsetLogfile file_p, logset configFile_p) : base (file_p.name)
		{
			file_i = file_p;
			configFile_i = configFile_p;
		}
		
		
		public override object Run()
		{
			return LoggingFormFactory.CreateForm(file_i, configFile_i);
			
		}
	}
	
}

